package com.yellow.chatservice.controller;

import com.alibaba.fastjson2.JSON;
import com.yellow.chatservice.common.SpringContextUtil;
import com.yellow.chatservice.entity.Friend;
import com.yellow.chatservice.entity.Messages;
import com.yellow.chatservice.feign.UserFeignService;
import jakarta.websocket.OnClose;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.CrossOrigin;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author: hy
 * @create: 2024-02-17
 */
@Slf4j
@CrossOrigin(origins = "*")
@Component
@ServerEndpoint(value="/websocket/{nickname}")
public class WebSocketController {

    private Session session;

    private String avatarUrl;
    /**
     * 好友列表
     */
    public static List<Friend>friendsList = new ArrayList<>();

    /**
     * 定义并发hashmap存储好友websocket集合
     */
    public static ConcurrentHashMap<String,WebSocketController> webSocketSession = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(@PathParam(value="nickname") String nickname, Session session){
            //设置session
            this.session = session;
            //put添加当前类
            webSocketSession.put(nickname,this);
            UserFeignService userFeignService = SpringContextUtil.getBean(UserFeignService.class);

            log.info("nickname:{}",nickname);
            this.avatarUrl = userFeignService.getAvatarByName(nickname);
            //add添加当前好友信息
            friendsList.add(Friend.builder().nickname(nickname).avatar(avatarUrl).build());
            //通知更新好友信息列表
             updateFriendInformationList();
             log.info("【WebSocket消息】有新的连接[{}],连接总数:{}",nickname,webSocketSession.size());

    }
    /**
     * 通知更新好友信息列表
     */
    private synchronized void updateFriendInformationList(){
        webSocketSession.forEach((key,val)->{
            //初始化存储自己的好友列表并排除自己
            List<Friend> friends = new ArrayList<>();
            //迭代所有好友列表
            friendsList.forEach((friend)->{
                //在所有好友列表中验证非自己
                if(!friend.getNickname().equals(key)){
                    //追加非自己的好友信息
                    friends.add(friend);
                }
            });
            //发送消息
            sendP2PMessage(key, JSON.toJSONString(Messages.builder().type("updateFriendsList").receiveNickname(key).messages(friends).build()));
        });
    }

    @OnMessage
    public void onMessage(@PathParam(value="nickname") String nickname,String message){
        log.info("【WebSocket消息】 收到客户端[{}] 发送消息:{} 连接总数:{}",nickname,message,webSocketSession.size());
        //验证消息内容
        if(StringUtils.hasLength(message)){
            try{
                log.info("【WebSocket消息】消息转对象:{}",message);
                //消息内容转消息对象
                Messages messages = JSON.parseObject(message,Messages.class);
                //发送消息
                messages.setAvatar(this.avatarUrl);
                message = JSON.toJSONString(messages);
                sendP2PMessage(messages.getReceiveNickname(),message);
            }
            catch(Exception e){
                log.error("WebSocket消息异常:",e);
            }
        }
    }

    @OnClose
    public void onClose(@PathParam(value = "nickname") String nickname){
        friendsList.remove(friendsList.stream().filter((friends -> friends.getNickname().equals(nickname))).findAny().orElse(null));
        webSocketSession.remove(nickname);
        //通知更新好友信息列表
        updateFriendInformationList();
        log.info("【WebSocket消息】客户端[{}]连接断开, 剩余连接总数:{}",nickname,webSocketSession.size());
    }


    /**
     * 点对点发送
     */

    public static synchronized void sendP2PMessage(String nickname,String message){
        log.info("【WebSocket消息】点对点发送消息,nickname={} , message={}",nickname,message);
        try{
            webSocketSession.get(nickname).session.getBasicRemote().sendText(message);
        }
        catch (Exception e){
            log.error("点对点发送异常:",e);
        }
    }

}
